/*******************************************************************************
 * Copyright (C) 2010 Devin Samarin.
 * 
 * This file is part of the SUIT Toolkit.
 * 
 * The SUIT Toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The SUIT Toolkit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the SUIT Toolkit.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package suit.ui;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

/**
 * A Widget that displays a small amount of text.
 * 
 * All the difficult parts about rendering text are taken care of here, such as
 * word wrapping, fonts, alignment.
 * 
 * Although you can pack multiple lines into a Label, there does come a point
 * when the amount of text you're trying to show gets out of hand. At that point
 * you might want to investigate the TextView Widget.
 * 
 * @author Devin Samarin
 * 
 */
public class Label extends Widget {

	private String label = "";
	private String[] split = {};
	private Font font = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN,
			Font.SIZE_LARGE);

	private boolean changed = true;

	protected int align = 0;
	/**
	 * Constant for aligning Label text to the left
	 */
	public static final int LEFT = 1;
	/**
	 * Constant for aligning Label text to the right
	 */
	public static final int RIGHT = 2;
	/**
	 * Constant for aligning Label text horizontally to the center
	 */
	public static final int CENTER = 4;
	/**
	 * Constant for aligning text without leaving space at the end (Not
	 * implemented)
	 */
	public static final int JUSTIFY = 8; // Not implemented

	/**
	 * Constant for aligning Label text to the top
	 */
	public static final int TOP = 16;
	/**
	 * Constant for aligning Label text to the bottom
	 */
	public static final int BOTTOM = 32;
	/**
	 * Constant for aligning Label text vertically to the center
	 */
	public static final int VCENTER = 64;
	/**
	 * Constant for aligning the baseline of the text to the middle of the label
	 */
	public static final int BASELINE = 128;

	protected Color color;

	/**
	 * Constructs a new Label without an empty String
	 */
	public Label() {
		setText("");
	}

	/**
	 * Constructs a new Label with the specified text
	 * 
	 * @param text
	 *            the specified text
	 */
	public Label(String text) {
		setText(text);
	}

	protected Rectangle getRequisition() {
		int h = font.getHeight() * (Misc.count(label, '\n') + 1);
		return new Rectangle(0, 0, font.stringWidth(Misc.longestLine(split)), h);
	}

	protected boolean onExpose(Event e) {
		if (changed) {
			wordWrap();
			changed = false;
		}
		int x, y, anchorX, anchorY;
		for (int i = 0; i < split.length; i++) {
			if ((align & LEFT) == LEFT) {
				x = allocation.x;
				anchorX = Graphics.LEFT;
			} else if ((align & RIGHT) == RIGHT) {
				x = allocation.x + allocation.w;
				anchorX = Graphics.RIGHT;
			} else { // Align CENTER by default
				x = allocation.x + allocation.w / 2;
				anchorX = Graphics.HCENTER;
			}
			if ((align & TOP) == TOP) {
				y = allocation.y;
				anchorY = Graphics.TOP;
			} else if ((align & BOTTOM) == BOTTOM) {
				y = allocation.y + allocation.h;
				anchorY = Graphics.BOTTOM;
			} else if ((align & BASELINE) == BASELINE) {
				y = allocation.y + allocation.h / 2;
				anchorY = Graphics.BASELINE;
			} else { // Align VCENTER by default
				y = allocation.y + allocation.h / 2 - font.getHeight()
						* split.length / 2;
				anchorY = Graphics.TOP;
			}
			try {
				e.theme.setLabelText(e.graphics);
				e.graphics.drawString(split[i], x, y + font.getHeight() * i,
						anchorX | anchorY);
			} catch (NullPointerException n) {
			}
		}
		return false;
	}

	/**
	 * Align the Label's text according to align (e.g.
	 * Label.CENTER|Label.VCENTER)
	 * 
	 * @param align
	 *            the alignment of the text
	 */
	public void setAlign(int align) {
		this.align = align;
		invalidate(this);
	}

	/**
	 * Sets the contents of the label.
	 * 
	 * @param text
	 *            the text of the label
	 */
	public void setText(String text) {
		if (!text.equals(label)) {
			changed = true;
			this.label = text;
			invalidate(this);
		}
	}

	protected void sizeAllocate(Rectangle a) {
		try {
			if (a.w != allocation.w) {
				changed = true;
			}
		} catch (NullPointerException e) {
		}
		super.sizeAllocate(a);
	}

	/**
	 * Returns the text of the label
	 * 
	 * @return the text of the label
	 */
	public String getText() {
		return this.label;
	}

	private void wordWrap() {

		// Homegrown wordwrap function v2 :)

		int space = allocation.w;
		label = label.trim()+" ";
		int len = label.length();

		if (len == 1) {
			split = new String[] { "" };
			return;
		}

		StringBuffer buffer = new StringBuffer(len);

		char[] breakchars = { ' ', '\n', '\t', '-' };

		int lastbreak = 0;
		int lastspace = 0;
		char curch;
		for (int i = 0; i < len; i++) {
			curch = label.charAt(i);
			if (Misc.inArray(breakchars, curch)) {
				if (font.stringWidth(label.substring(lastbreak, i).trim()) >= space) {
					if (lastspace != 0) {
						switch (label.charAt(lastspace)) {
						case '\n':
							break;
						case '-':
							buffer.insert(lastspace + 1, '\n');
							break;
						case ' ':
							buffer.setCharAt(lastspace, '\n');
							break;
						default:
							buffer.insert(lastspace, '\n');
						}
					}
					lastbreak = i + 1;
				}
				lastspace = i;
			}
			buffer.append(curch);
		}
		label = label.trim();
		split = Misc.splitString(buffer.toString().trim(), '\n');
	}
}
